<template>
<div class="column outer">

    <div class="viewport grow" ref="refViewport">
        <div class="full" style="position:absolute" ref="refViewsrow">

            <Graph ref="refViewGraph" name="refViewGraph" class="active view"></Graph>
            <UI ref="refViewUI" name="refViewUI" class="view"></UI>
            <Program ref="refViewProgram" name="refViewProgram" class="view"></Program> 

        </div>
    </div>

    <!-- 模型属性 -->
    <n-modal v-model:show="bPopupProperties" preset="card" style="width: 600px" :bordered="false" size="huge" role="dialog" aria-modal="true">
        <AppProperties ref="refAppProps"></AppProperties>
        <div class="row end">
            <n-button size="large" @click="bPopupProperties=false">完成</n-button>
        </div>
    </n-modal>

    <div style="position: absolute;bottom:5px;right: 5px">
        <StrechyViewMenu ref="refStrechyMenu" @change-view="changeView" @action="menuAction"></StrechyViewMenu>
    </div>
</div>
</template>

<style>
.modeldetail-tabs .ivu-tabs-bar {
    margin-bottom: 6px;
}
</style>

<style scoped>
.outer {
    background-color: wheat;
}
.viewport {
    overflow: hidden;
}
.view {
    height: 100%;
    overflow-x: hidden;
    overflow-y: auto;
    float: left;
    position: absolute;
}
</style>

<script lang="ts" setup>
import {ref, onMounted, Ref, reactive, getCurrentInstance, nextTick} from 'vue'
import Program from "./program/Program.vue";
import UI from "./ui/UI.vue"
import Graph from "./graph/Graph.vue"
import { AppModel } from "../../model/AppModel";
import {saveModel} from './saver'
import { conn } from "@beshell/conn-ts/Connection";
import { bus } from '@beshell/events-ts/bus';
import AppProperties from './AppProperties.vue';

import {useMessage} from 'naive-ui'
const message = useMessage()


const refViewport = ref(null) as unknown as Ref<HTMLElement>
const refViewsrow = ref(null) as unknown as Ref<HTMLElement>
const refViewGraph = ref(null) as unknown as Ref<typeof Graph>
const refViewUI = ref(null) as unknown as Ref<typeof UI>
const refViewProgram = ref(null) as unknown as Ref<typeof Program>
const refAppProps = ref(null) as unknown as Ref<typeof AppProperties>
const refStrechyMenu = ref(null) as unknown as Ref<typeof AppProperties>

let $viewport: any
let $viewsrow: any
let $views: any


const activePanel = ref("0")

const bPopupProperties = ref(false)

let model:AppModel

const instance = getCurrentInstance()


onMounted(()=>{
    const refs: any = (instance?.refs) || {}

    $viewport = $(refViewport.value)
    $viewsrow = $(refViewsrow.value)
    $views = $(refViewsrow.value).find(".view").each(function (index: number){
        $(this)
            .data( "view", refs[$(this).attr('name') as string] )
            .data( "index", index )

        if(index.toString()!=activePanel.value)
            $(this).hide()
    })
    ;(window as any).$views = $views


    $(window).resize(onResize)

    console.log("xxxx refAppProps.value:",refAppProps.value)
})


function initView() {
    onResize()

    // 初始化 scratch
    // scratch 不能在 hide 状态下初始化
    $views.eq(2)
            .show()
            .css('left', $views.eq(0).width())
    refViewProgram.value?.enter()

    activePanel.value = "0"
}



function onResize() {
    
    let width = $viewport.width()
    let height = $viewport.height()

    $viewsrow.width(width*3)
    $viewsrow.height(height)

    $views.width(width)
    $views.height(height)

    refViewUI.value.onResize(width, height)
}

// 切换 panel 的动画实现
function swipeView(to: any) {
    let from = $viewsrow.find(".view.active").data("index")
    to = parseInt(to)
    if(to == from)
        return

    let width: number = $views.eq(from).width()
    if(from>to) {
        var pos = width
    }
    else {
        var pos = -width
    }
    
    $views.each(function(i:number) {
                    if(i==to || i==from){
                        // @ts-ignore
                        $(this).show()
                    } else {
                        // @ts-ignore
                        $(this).hide()
                    }
                })
                .eq(to)
                .css('left', -pos)

    $viewsrow.css("left", 0)

    $viewsrow.animate({
        left: pos
    }, 300, "swing", ()=>{
        $views.eq(from).hide().removeClass("active")
        $viewsrow.css("left", 0)
        $views.eq(to).css("left", 0).addClass("active")

    })

    let toView = $views.eq(to).data("view")
    if(toView.enter) {
        toView.enter()
    }
    let fromView = $views.eq(from).data("view")
    if(fromView.leave) {
        fromView.leave()
    }
}
// watch(activePanel, swipeView)

function load(_model: AppModel) {
    activePanel.value = "0"

    model = _model
    AppModel.active = _model

    setTimeout(()=>{

        initView()

        refViewGraph.value.setModel(model)
        refViewUI.value.setModel(model)
        refViewProgram.value.setModel(model)

    }, 0)
}
async function open(remoteLocal: string) {

    bus.emit("spin-fullpage.show()", "加载APP ...")

    let model = new AppModel()

    try{
        if(!await model.load(remoteLocal, (msg:string)=>{
            bus.emit("spin-fullpage.message()", msg)
        })) {
            throw new Error()
        }

        // 设置为启动模型
        // let mainJsPath = model.folderPath + '/main.js'
        // await conn.console.call(`require("/etc/init.d/app.js").setAutoBootPath("${mainJsPath}")`)

        // 重置
        bus.emit("spin-fullpage.message()", '正在等待主机零件就绪 ...')
        await conn.console.reset()

        // 在远程零件上执行 beconsole 的相关初始化
        await model.remoteSetup()

        load(model)
        
    }catch(e:any){
        console.error(e)
        message.error("加载APP遇到了错误")
    }

    bus.emit("spin-fullpage.hide()")

    ;(window as any).model = model
}

function leave() {
    refStrechyMenu.value.close()
}

function changeView(viewName:string, viewIdx:number) {
    swipeView(viewIdx)
}
function menuAction(action:string) {
    if(action=='save') {
        saveModel(model, refViewGraph.value.serialize(), refViewProgram.value.serialize())
    }
    else if(action=='edit') {
        console.log("edit",refAppProps.value)
        bPopupProperties.value = true

        nextTick(()=>{
            refAppProps.value.setModel(model)
        })
    }
}


defineExpose({load,open,leave})

</script>